<template>
    <rx-dialog :options="dialogOptions"  @close="close" @confirm="confirm">
    <div style="width:100%;height:100%" class="flowImg">
        <movable-area class="movable-area">
            <movable-view class="movable-view"  :x="-200" :y="0" direction="all"  scale="true" :scaleMin="0.2" :scaleMax="10"
                          :scale-value="scale" @change="onChange">
                <div class="containers" ref="content">
                    <div class="canvas" ref="canvas" style="width: 100%;height: 100%">
                    </div>
                </div>
            </movable-view>
        </movable-area>
    </div>
    </rx-dialog>
</template>

<script>
import BpmnViewer from 'bpmn-js/lib/NavigatedViewer'
import BpmModeler from 'bpmn-js/lib/features/modeling'
import {getBpmnXmlFromParam, getBpmnImageNodeInfo} from './bpmImage.js'
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
import nodeProperties from './flowstate'
import flowNode from './flowNode.js'
import baidu from 'baidutemplate/baiduTemplate'
import BaseDialogComponent from "@/components/layer/BaseDialogComponent.js";
import {
    append as svgAppend,
    attr as svgAttr,
    create as svgCreate,
    classes as svgClasses,
} from 'tiny-svg';

var propertiesConfig = {}

var bpmInst = {}

var isPreview =false

const rectConfig = (str)=>{
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    context.font = '12px Arial';
    const metrics = context.measureText(str);
    const width = metrics.width;

    let size = Math.ceil(width) > 40? Math.ceil(width) + 6 : 40 ;
    return {
        rectWidth:size,
        rectX:(100 - size) / 2,
        textX:(100 - width) / 2
    }
}

function createNode(parentNode,config){
    let rect = svgCreate('rect');
    let rectObj = rectConfig(config.name)
    svgAttr(rect, {
        x: rectObj.rectX,
        y: -20,
        rx:2,
        ry:2,
        width:rectObj.rectWidth,
        height:20,
        class:'bpm-',
        fill:config.stroke
    });
    let text = svgCreate('text');
    svgAttr(text,{
        x:rectObj.textX,
        y:-5,
        fill:'#fff',
        fontSize:'12px'
    })
    let tspan = svgCreate('tspan');
    tspan.innerHTML = config.name ;
    svgAppend(text,tspan);
    svgAppend(parentNode,rect);
    svgAppend(parentNode,text);
}
class CustomRenderer extends BaseRenderer {
    constructor(eventBus, bpmnRenderer) {
        super(eventBus, 1500);
        this.bpmnRenderer = bpmnRenderer;
        console.log(bpmnRenderer);
    }

    canRender(element) {
        // ignore labels
        const type = element.type // 类型
        return !element.labelTarget;
    }

    drawShape(parentNode, element) {
        let shape = this.bpmnRenderer.drawShape(parentNode, element);
        setShapeProperties(shape, element, parentNode) // 在此修改shape
        return shape
    }
    getShapePath(shape) {
        return this.bpmnRenderer.getShapePath(shape);
    }

}

function setShapeProperties(shape, element, parentNode) {
    const id = element.id;//获取到的节点ID
    const type = element.type // 获取到的类型
    //开始节点和结束节点加上颜色
    if(isPreview &&  (type=="bpmn:StartEvent" || (bpmInst.status=='SUCCESS_END' && type=="bpmn:EndEvent")) ){
        shape.style.setProperty("stroke", '#83cd6c');
        return;
    }
    if (propertiesConfig[type + ":" + id]) {
        const properties = propertiesConfig[type + ":" + id];
        if(properties.stroke){
            shape.style.setProperty('stroke',properties['stroke']);
        }
        if(properties.fill){
            shape.style.setProperty('fill',properties['fill']);
        }
        createNode(parentNode,properties)
    }
}

CustomRenderer.$inject = ['eventBus', 'bpmnRenderer']

export default {
    name: "BpmImageView",
    components: {
        flowNode
    },
    props: {
        instId: String,
        taskId: String,
        defId: String,
        formData: Object,
        showTips: {
          tyep:Boolean,
          default:true
        },
        preview: {
            tyep:Boolean,
            default:false
        },
        startUserId:String
    },
    mixins:[BaseDialogComponent],
    data() {
        return {
            nodeAry: {
              UserTask:"bpmn:UserTask",
              "ReceiveTask":"bpmn:ReceiveTask",
              "ServiceTask":"bpmn:ServiceTask"
            },
            histories:[],
            extConfs:"",
            x: 0,
            y: 0,
            scale: 0.5,
            old: {
                scale: 1
            },
        }
    },
    created() {
        this.init();
    },
    methods: {
        tap: function(e) {
            this.x = this.old.x
            this.y = this.old.y
            this.$nextTick(function() {
                this.x = 30
                this.y = 30
            })
        },
        onChange: function(e) {
            this.old.x = e.detail.x
            this.old.y = e.detail.y
        },
        i18n(name,text,key){
            return this.$ti18(name,text,"bpmInst",key);
        },
        psrseExtConfs(extConfsStr){
            if(!extConfsStr){
                return;
            }
            this.extConfs=JSON.parse(extConfsStr);
        },
        getNodeI18Name(nodeId,textVal){
            let node = this.extConfs[nodeId];
            if(!node || !node.i18nJson){
                return textVal;
            }
            let name= this.$i18(node.i18nJson,'节点名称');
            if(!name){
                return textVal;
            }
            return name;
        },
        setLineLable(){
            if(!this.extConfs){
                return;
            }
            let self = this ;
            this.modeling = this.viewer.get('modeling');
            const elementAll = this.viewer.get('elementRegistry').getAll();
            elementAll.forEach(elm=>{
                let elmId = elm.id ;
                let name = self.getNodeI18Name(elmId,"");
                if(!name){
                    return;
                }
                let shape = self.viewer.get('elementRegistry').get(elmId);
                if (shape) {
                    self.modeling && self.modeling.updateProperties(shape, {id: elmId, name: name});
                }
            });
        },
        setLineColor(nodeIds,pathMap){
            if(!nodeIds || nodeIds.length==0){
                return;
            }
            const elementAll = this.viewer.get('elementRegistry').getAll();
            let lines = [],ExclusiveGateway=[];//ExclusiveGateway网关节点
            elementAll.forEach(elm=>{
                let isLine = elm.source || elm.target ;
                if(isLine){// 是否是线条 ；
                    let firstId = elm.source.id ;
                    let lastId = elm.target.id ;
                    if(firstId.indexOf('ExclusiveGateway')> -1){
                        ExclusiveGateway.push(elm.source);
                    }
                    if(pathMap && pathMap[firstId] && pathMap[firstId].includes(lastId)){
                        lines.push(elm);
                    }
                }
            })
            //删选 线条走过的网关节点
            let concatLine = [];
            for (let node of lines){
                if(node && node.type == "bpmn:SequenceFlow"
                    && node.target && node.target.type=="bpmn:ExclusiveGateway"
                ){
                    let ExclusiveGateway_id = node.target.id ;
                    let findExclusiveGateway = ExclusiveGateway.find(exclus=>exclus.id == ExclusiveGateway_id);
                    let hasConcatLine = concatLine.find(item=>item.id == ExclusiveGateway_id);
                    if(findExclusiveGateway && !hasConcatLine){
                        concatLine.push(findExclusiveGateway);
                    }
                }
            }
            const modeling = this.viewer.get('modeling');
            let ary = [...lines,...concatLine];
            if(ary.length==0){
              return;
            }
            modeling.setColor(ary, {
                stroke: '#83cd6c'
            });
        },

        createHtml(json) {
            let nodeId = json.taskNodeUser.nodeId;
            json.taskNodeUser.nodeText =this.getNodeI18Name(nodeId,json.taskNodeUser.nodeText);
            var _html = baidu.template(flowNode, {data:json,baidu});
            return _html;
        },
        getNodeId(nodeId) {
            for (var key in this.nodeAry) {
                if (nodeId.indexOf(key) != -1) {
                    return this.nodeAry[key] + ':' + nodeId;
                }
            }
        },
        init() {
            let self = this;
            isPreview=this.preview;
            this.$nextTick().then(() => {
                this.canvas = this.$refs.canvas;
                if (!this.viewer) {
                    this.viewer = new BpmnViewer({
                        container: this.canvas,
                        keyboard: {
                            bindTo: window
                        },
                        additionalModules: [
                            {
                                __init__: ['customRenderer'],
                                customRenderer: ['type', CustomRenderer]
                            },
                            BpmModeler
                        ]
                    })
                }

                //从后台xml中获取
                getBpmnXmlFromParam({
                    defId: self.defId,
                    instId: self.instId,
                    taskId: self.taskId,
                    showHis: true,
                    preview: this.preview,
                    formData:this.formData,
                    startUserId:this.startUserId
                }).then(result => {
                    if (!result) {
                        return;
                    }
                    self.psrseExtConfs(result.extConfs);
                    propertiesConfig = {};
                    bpmInst = {};
                    let nodeIds = [];
                    if(result.bpmInst!=null) {
                        bpmInst = Object.assign(bpmInst,result.bpmInst);
                    }
                    if (result.histories != null) {
                        self.histories=result.histories;
                        for (let i = 0; i < result.histories.length; i++) {
                            var checkStatus = result.histories[i].checkStatus;
                            if (checkStatus == 'TRANSFER' || checkStatus == 'ROAM_TRANSFER' || checkStatus == 'COMPLETED') {
                                //转办历史跳过
                                continue;
                            }
                            nodeIds.push(result.histories[i].nodeId);
                            propertiesConfig[this.getNodeId(result.histories[i].nodeId)] = nodeProperties[checkStatus];
                        }
                    }
                    this.viewer.importXML(result.bpmnXml, function (err) {
                        if (err) {
                            console.log('error rendering', err);
                        } else {
                            console.log('rendered');
                        }
                        const eventBus = self.viewer.get('eventBus');
                        const overlays = self.viewer.get('overlays');
                        //国际化名称计算
                        self.setLineLable();
                        //设置流程走过的线条的颜色；
                       // if(self.preview){
                        let { pathMap } = result ;
                        self.setLineColor(nodeIds,pathMap)
                       // }
                        var ishovers = false;
                        var _id = ''
                        if(!self.showTips){
                          return;
                        }
                        eventBus.on('element.click', (e) => {
                            if (e.element.type != 'bpmn:UserTask') {
                                overlays.clear();
                                ishovers = false;
                                return;
                            }
                            if (e.element.id && _id != e.element.id) {
                                if (overlays) {
                                    overlays.clear();
                                }
                                overlays.clear();
                                ishovers = false;
                                _id = e.element.id;
                            }
                            if (ishovers) {
                                return;
                            }
                            if(self.preview){
                                var json={
                                    taskNodeUser:{
                                        "nodeId": e.element.id,
                                        "nodeText": "",
                                        "nodeType": e.element.type,
                                        "multiInstance": "normal",
                                        "actDefId": "",
                                        "configExecutors": [],
                                    },
                                    histories:[]
                                };
                                self.histories.find(item=>{
                                    if(item.nodeId==e.element.id){
                                        json.histories.push(item);
                                        var executor={
                                            "type": "user",
                                            "id": item.handlerId,
                                            "name": item.handlerUserName,
                                            "account": item.handlerUserNo,
                                            "calcType": "none"
                                        };
                                        json.taskNodeUser.nodeText=item.nodeName;
                                        json.taskNodeUser.actDefId=item.actDefId;
                                        json.taskNodeUser.configExecutors.push(executor);
                                    }
                                });

                                if(json.histories.length>0){
                                    const $overlayHtml = self.createHtml(json);
                                    overlays.add(e.element.id, {
                                        position: {top: e.element.height, left: -92},
                                        html: $overlayHtml
                                    });
                                }
                            }else {
                                getBpmnImageNodeInfo({
                                    taskId: self.taskId,
                                    instId: self.instId,
                                    defId: self.defId,
                                    nodeId: e.element.id,
                                    formData: self.formData
                                }).then(json => {
                                    if (!json.taskNodeUser) {
                                        return;
                                    }

                                    const $overlayHtml = self.createHtml(json);
                                    overlays.add(e.element.id, {
                                        position: {top: e.element.height, left: -92},
                                        html: $overlayHtml
                                    });
                                })
                            }
                            self.itemClick(overlays);
                            ishovers = true;
                        });

                    });
                });
            });
        },
        itemClick(overlays) {
            var dom = overlays._overlayRoot;
            dom.removeEventListener('click', this.btnClick);
            dom.addEventListener('click', this.btnClick)
        },
        btnClick(e) {
            var ev = e || window.event;
            var target = ev.target || ev.srcElement;
            if (target.className.includes('flow-item-btn')) {
                var li = target.parentNode.parentNode.parentNode;
                var lichiren = li.parentNode.getElementsByClassName('flow-item-li');
                for (let i = 0; i < lichiren.length; i++) {
                    if (lichiren[i] != li) {
                        lichiren[i].className = "flow-item-li";
                        lichiren[i].getElementsByClassName('flow-item-btn')[0].innerText = this.$ti18('rxList.openBtn', '展开');
                    }
                }
                if (li.className.includes("flow-item-li")) {
                    if (li.className.includes('active')) {
                        target.innerText = "展开";
                        li.className = "flow-item-li"
                    } else {
                        target.innerText = this.$ti18('rxList.putAwayBtn', '收起');
                        li.className = "flow-item-li active"
                    }
                }

            }
        },
        confirm(){
            this.dialogClose({action:'ok',data:'data'})
        },
        close(){
            this.dialogClose({action:'no',data:'data'})
        }
    }
}
</script>

<style scoped>
.flowImg{
    position: relative;
}
.flowImg>>>uni-movable-view{
    width: 400%!important;
    height: 400% !important;
}
movable-view {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    width: 100%;
    text-align: center;
}

.movable-area {
    height: 100%;
    width: 100%;
    position: absolute;
    overflow: hidden;
}
.containers {
    height: calc(100% - 44px);
    width: 150%;
}

.djs-container > svg {
    overflow: auto !important;
}

.djs-connection path {
    stroke: blue !important;
    marker-end: url(#sequenceflow-arrow-normal) !important;
}
.flow-item-details{
    /*border:solid 1px #ccc;*/
    padding-top:4px;
}
.split-line{
    border-top: dotted 1px #ccc;
    height:2px;
    padding-bottom: 6px;
}
</style>
